Material UI is a Material Design library made for React.
It’s a set of React components that have Material Design styles.
In this article, we’ll look at how to add modals with Material UI.
Modal
We can use the Modal
component to display dialog boxes our way.
To create a simple one, we can write:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
function getModalStyle() {
const top = 50;
const left = 50;
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`
};
}
const useStyles = makeStyles(theme => ({
paper: {
position: "absolute",
width: 300,
backgroundColor: theme.palette.background.paper,
padding: 20
}
}));
export default function App() {
const classes = useStyles();
const [modalStyle] = React.useState(getModalStyle);
const [open, setOpen] = React.useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const body = (
<div style={modalStyle} className={classes.paper}>
<h2>Modal</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. </p>
<SimpleModal />
</div>
);
return (
<div>
<button type="button" onClick={handleOpen}>
Open Modal
</button>
<Modal open={open} onClose={handleClose}>
{body}
</Modal>
</div>
);
}
to create a simple modal.
We added some styles with the makeStyles
component and the getModalStyle
function.
We used makeStyles
to set the background color and the positioning of the content.
We change the position to absolute so that it displays above everything else.
getModalStyle
is used for positioning the modal.
Transitions
We can animate the modal with a transition component.
For instance, we can write:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
import Backdrop from "@material-ui/core/Backdrop";
import Fade from "@material-ui/core/Fade";
const useStyles = makeStyles(theme => ({
modal: {
display: "flex",
alignItems: "center",
justifyContent: "center"
},
paper: {
backgroundColor: theme.palette.background.paper,
border: "2px solid gray",
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3)
}
}));
export default function App() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<button type="button" onClick={handleOpen}>
open modal
</button>
<Modal
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500
}}
>
<Fade in={open}>
<div className={classes.paper}>
<h2>fade modal</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</Fade>
</Modal>
</div>
);
}
to create a modal with a fade transition when we open or close it.
This is done with the Fade
component.
The in
prop specifies that we show the transition when open
is true
.
We then have what we want to display inside the modal.
We open the modal when we click the open modal button.
And we can click outside when we close it.
handleOpen
sets the open
state to true
to open the modal.
hanleClose
closes the modal to close the modal.
onClose
is run when we click outside the modal.
BackdropComponent
sets the component for the backdrop.
closeAfterTransition
lets us wait until a nested transition is done before closing.
Also, we can use the react-spring package to add the transition:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
import Backdrop from "@material-ui/core/Backdrop";
import { useSpring, animated } from "react-spring/web.cjs"; // web.cjs is required for IE 11 support
const useStyles = makeStyles(theme => ({
modal: {
display: "flex",
alignItems: "center",
justifyContent: "center"
},
paper: {
backgroundColor: theme.palette.background.paper,
border: "2px solid #000",
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3)
}
}));
const Fade = React.forwardRef(function Fade(props, ref) {
const { in: open, children, onEnter, onExited, ...other } = props;
const style = useSpring({
from: { opacity: 0 },
to: { opacity: open ? 1 : 0 },
onStart: () => {
if (open && onEnter) {
onEnter();
}
},
onRest: () => {
if (!open && onExited) {
onExited();
}
}
});
return (
<animated.div ref={ref} style={style} {...other}>
{children}
</animated.div>
);
});
export default function SpringModal() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<button type="button" onClick={handleOpen}>
open menu
</button>
<Modal
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500
}}
>
<Fade in={open}>
<div className={classes.paper}>
<h2>Spring modal</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</Fade>
</Modal>
</div>
);
}
We created the Fade
component.
We use the useSpring
hook provided by react-spring to add the animation.
We specify the transition style for the in transition in the friom
property.
Also, we specify the transition style for the out transition with the to
property.
onStart
and onExited
are functions that’s called when the transition starts and ends respectively to start and finish the transition.
Then we use Fade
in the modal.
Conclusion
We can create modals with transitions by using components from Material UI or react-spring.